package com.ht.api.db.metadata;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.ht.api.db.Db;
import com.ht.api.db.DbList;
import com.ht.api.db.Entity;
import com.ht.api.db.SqlParser;
import com.ht.api.db.bean.DbSql;
import com.ht.api.db.util.HtUtil;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;

/**
 * 数据库元数据管理器:列
 * @author asq
 * @createTime 2024年12月4日 14:01:29
 */
public class ColumnMetadataManager extends AbstractMetadataManager {
	/**
	 * 返回一个实例
	 * @return
	 */
	public static AbstractMetadataManager create() {
		return new ColumnMetadataManager();
	}

	@Override
	public DbList find(SqlParser sqlParser) {
		return SqlParser.create("db_column").where("code", sqlParser.getTable()).query();
	}

	@Override
	protected DbSql addData(Entity entity) {
		// 获取要插入的列信息
		String tableCode = entity.getStr("table_code");
		String code = entity.getStr("code");
		String name = entity.getStr("name");
		String type = entity.getStr("type");
		String fun = entity.getStr("fun");
		String def = entity.getStr("default_value");
		String remark = entity.getStr("remark");
		String primary = entity.getStr("primary");
		String orderNum = entity.getStr("order_num");
		String dictId = entity.getStr("dict_id");
		String mapperConfig = entity.getStr("mapper_config");
		String sysTime = DateUtil.now();
		orderNum = orderNum == null ? "0" : orderNum; // 确保orderNum字段不为null
		fun = fun == null ? "REPLACE_IF_NOT_NULL" : fun;

		// 要返回的sql对象
		String tableMainId = HtUtil.getId();
		DbSql dbSql = new DbSql();
		dbSql.appendSql("insert into db_column(main_id,sys_time,sys_deleted,sys_creator,table_code,code,name,type,fun,"
				+ "default_value,primary_key,remark,order_num,dict_id,mapper_config) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);");
		dbSql.appendParam(tableMainId, sysTime, 1, 0, tableCode, code, name, type, fun, def, primary, remark, 
				orderNum, dictId, mapperConfig);
		entity.set("main_id", tableMainId);
		return dbSql;
	}

	@Override
	protected DbSql addSchema(Entity entity) {
		String tableCode = entity.getStr("table_code");
		String code = entity.getStr("code");
		String name = entity.getStr("name");
		String type = entity.getStr("type");
		String fun = entity.getStr("fun");
		String def = entity.getStr("default_value");

		// 生成sql
		StringBuilder columnSql = StrUtil.builder();
		columnSql.append("ALTER TABLE ").append("`" + tableCode + "`");
		columnSql.append(" ADD COLUMN ").append("`" + code + "`");
		columnSql.append(" " + getPropertyType(type) + " ");
		columnSql.append(StrUtil.isBlank(fun) ? " REPLACE_IF_NOT_NULL " : fun);
		if (StrUtil.isNotBlank(def)) {
			columnSql.append(" DEFAULT '" + def + "' ");
		}
		if (StrUtil.isNotBlank(name)) {
			columnSql.append(" COMMENT '" + name + "' ");
		}
		columnSql.append(";");
		
		return new DbSql().setSql(columnSql.toString());
	}

	@Override
	protected DbSql modifyData(Entity entity) {
		String mainId = entity.getStr("main_id");
		
		// 组装sql和参数
		List<Object> params = new ArrayList<>();
		StringBuilder sb = new StringBuilder();
		sb.append("update db_column set sys_time=sys_time");
		List<String> fieldList = Arrays.asList("code", "name", "type", "fun", "primary_key", 
				"remark", "order_num", "dict_id", "mapper_config");
		fieldList.stream().forEach(key -> {
			String value = entity.getStr(key);
			if (value != null) {
				sb.append(String.format(",%s=?", key));
				params.add(value);
			}
		});
		sb.append(" where main_id=?;");
		params.add(mainId);

		// 返回sql对象
		DbSql dbSql = new DbSql();
		dbSql.appendSql(sb.toString());
		dbSql.appendParam(params);
		return dbSql;
	}

	@Override
	protected DbSql modifySchema(Entity entity) {
		// 要返回的sql对象
		DbSql dbSql = new DbSql();
		
		// 获取各字段信息
		String tableCode = entity.getStr("table_code");
		String code = entity.getStr("code");
		String name = entity.getStr("name");
		String type = entity.getStr("type");
		String fun = entity.getStr("fun");
		//String def = entity.getStr("default_value");

		// 生成sql
		StringBuilder columnSql = StrUtil.builder();
		columnSql.append("ALTER TABLE ").append("`" + tableCode + "`");
		
		// 先RENAME
		Entity oldEntity = Db.createSqlParser("db_column").findById(entity.get("main_id"));
		String oldPropertyCode = oldEntity.getStr("code");
		if (code != null && !code.equals(oldPropertyCode)) {
			dbSql.appendSql(columnSql.toString() + " RENAME COLUMN `" + oldPropertyCode + "` `" + code + "`;");
		}
		
		// 再MODIFY
		String oldType = oldEntity.getStr("type");
		String oldName = oldEntity.getStr("name");
		type = type == null ? oldType : type; // 如果没有修改type，则使用旧type
		code = code == null ? oldPropertyCode : code; // 如果没有修改code，则使用旧code
		name = name == null ? oldName : name; // 如果没有修改name，则使用旧name
		if (!oldType.equals(type) || !oldName.equals(name)) {
			columnSql.append(" MODIFY COLUMN ").append("`" + code + "` ");
			columnSql.append(getPropertyType(type) + " ");
			columnSql.append(StrUtil.isBlank(fun) ? "REPLACE_IF_NOT_NULL" : fun);
			if (StrUtil.isNotBlank(name)) {
				columnSql.append(" COMMENT '" + name + "' ");
			}
			columnSql.append(";");
			
			dbSql.appendSql(columnSql.toString());
		}
		return dbSql;
	}

	@Override
	protected DbSql delData(Entity entity) {
		DbSql dbSql = new DbSql();
		dbSql.appendSql("delete from db_column where table_code=? and code=?;");
		dbSql.appendParam(entity.getStr("table_code"), entity.getStr("code"));
		return dbSql;
	}

	@Override
	protected DbSql delSchema(Entity entity) {
		DbSql dbSql = new DbSql();
		dbSql.appendSql(String.format("ALTER TABLE `%s` DROP COLUMN `%s`;", entity.getStr("table_code"), entity.getStr("code")));
		return dbSql;
	}

	@Override
	protected boolean isTable() {
		return false;
	}
	
	/**
	 * 返回字段类型
	 * @param propertyType
	 * @return
	 */
	private String getPropertyType(String propertyType) {
		String type = null;
		if (propertyType.equals("date")) {
			type = "varchar(10)";
		} else if (propertyType.equals("datetime")) {
			type = "varchar(19)";
		} else if (propertyType.equals("timestamp")) {
			type = "varchar(19)";
		} else if (propertyType.equals("decimal")) {
			type = "decimal(10,2)";
		} else if (propertyType.equals("varchar")) {
			type = "varchar(200)";
		} else if (propertyType.equals("longtext")) {
			type = "string";
		} else {
			type = propertyType;
		}
		return type;
	}
}
